package com.credithc.fastdfs.api.service.impl;

import java.io.File;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.credithc.fastdfs.api.bean.UploadReqBean;
import com.credithc.fastdfs.api.bean.UploadResBean;
import com.credithc.fastdfs.api.config.SystemConfig;
import com.credithc.fastdfs.api.entity.ErrorInfo;
import com.credithc.fastdfs.api.entity.FdfsInfo;
import com.credithc.fastdfs.api.exception.UploadException;
import com.credithc.fastdfs.api.service.ErrorInfoService;
import com.credithc.fastdfs.api.service.FdfsInfoService;
import com.credithc.fastdfs.api.service.FileUploadService;
import com.credithc.fastdfs.api.util.CommonUtil;
import com.credithc.fastdfs.api.util.FileUtil;
import com.credithc.fastdfs.api.validator.AnnexValidator;
import com.credithc.fastdfs.api.validator.ValidatorParmater;
import com.credithc.fastdfs.api.web.UploadCtrl;
import com.credithc.fastdfs.photo.util.PhotoUtils;
import com.credithc.fastdfs.util.FastdfsUtil;
import com.credithc.fastdfs.util.PathUtil;

/** 
 * @ClassName: FileUploadServiceImpl 
 * @Description: 文件上传实现
 * @author zhaoc
 * @date 2015年5月18日
 * @time  下午2:24:12 
 */ 
@Service("fileUploadService")
public class FileUploadServiceImpl implements FileUploadService {
	private Logger log = LoggerFactory.getLogger(UploadCtrl.class);
	
	@Resource(name = "fdfsInfoServiceImpl")
	public FdfsInfoService fdfsInfoServiceImpl;
	
	@Resource(name = "annexValidatorImpl")
	public AnnexValidator annexValidatorImpl;

	@Resource(name = "errorInfoService")
	protected ErrorInfoService baseErrorInfoService;
	
	@Override
	public boolean uploadTypeFile(UploadReqBean uploadReqBean,
			UploadResBean uploadResBean, HttpServletRequest request) throws UploadException {
		MultipartFile file = uploadReqBean.getFile();
		if (file == null || file.getSize() == 0) {
			throw new UploadException("文件内容为空", HttpStatus.UNPROCESSABLE_ENTITY);
		}
		if(StringUtils.isBlank(uploadReqBean.getFileType())) {
			throw new UploadException("文件类型为空", HttpStatus.UNPROCESSABLE_ENTITY);
		}
		String orgFileName = uploadReqBean.getFileName();
		orgFileName = (orgFileName == null) ? "" : orgFileName;
		FdfsInfo fdfsInfo = new FdfsInfo();
		fdfsInfo.setFileSize(file.getSize());// 文件大小
		fdfsInfo.setFileName(orgFileName);
		fdfsInfo.setSlaveName(uploadReqBean.getSlaveName());// 文件缩略图
		fdfsInfo.setFileType(uploadReqBean.getFileType());
		fdfsInfo.setBusinessId(uploadReqBean.getBusinessId());
		fdfsInfo.setSystemId(uploadReqBean.getSystemId());
		Map<String, Object> valiateMap = annexValidatorImpl.validateAnnex(fdfsInfo,ValidatorParmater.FileType.DOC.getKey());// 文档校验
		if(!(boolean) valiateMap.get("success")) {
			uploadResBean.setStatus(UploadCtrl.FAILED);
			uploadResBean.setMessage((String) valiateMap.get("msg"));
			log.warn(uploadResBean.getStatus()+":"+uploadResBean.getMessage());
			return false;
		}
		
		/**增加替换原始文件的验证*/
		FdfsInfo orginFdfsInfo=null;
		if(StringUtils.isNotBlank(uploadReqBean.getOrginFsId())){
			try {
	            orginFdfsInfo=fdfsInfoServiceImpl.selectByPrimaryKey(uploadReqBean.getOrginFsId());
	            if(orginFdfsInfo==null){
	            	throw new Exception("未找到原始文件id:"+uploadReqBean.getOrginFsId());
	            }
            } catch (Exception e) {
    			uploadResBean.setStatus(UploadCtrl.FAILED);
    			uploadResBean.setMessage(e.getMessage());
    			log.warn(uploadResBean.getStatus()+":"+uploadResBean.getMessage());
    			return false;
            }
		}
		
		try {
			String fileId = FastdfsUtil.getInstance().uploadFile(uploadReqBean.getFile().getBytes(), uploadReqBean.getFile().getOriginalFilename(), null);// 上传文件到服务器并返回fileId
			if(StringUtils.isBlank(fileId)) {//增加fileId 的判断 如果为null 或为空 则返回失败信息
				uploadResBean.setStatus(UploadCtrl.FAILED);
				uploadResBean.setMessage("文件上传失败,未获取到fileId");
				return false;
			}
			FdfsInfo fi = new FdfsInfo();
			fi.setFsId(CommonUtil.getUpperUUID());
			fi.setFileId(fileId);
			fi.setFileName(uploadReqBean.getFileName());
			fi.setFileSize(uploadReqBean.getFile().getSize());
			fi.setBusinessId(uploadReqBean.getBusinessId());
			fi.setFileType(uploadReqBean.getFileType());
			fi.setSystemId(uploadReqBean.getSystemId());
			fi.setUploadTime(new Date());
			fi.setUploadIp(CommonUtil.getIp(request));
			
			
			if(StringUtils.isNotBlank(uploadReqBean.getOrginFsId())){
				//替换原始文件
				fi.setFsId(uploadReqBean.getOrginFsId());
				fdfsInfoServiceImpl.updateFdfsInfoByPrimaryKey(fi);
				ErrorInfo errlog = new ErrorInfo(UUID.randomUUID().toString().replaceAll("-", ""), "upload", 
						String.format("fsid[%s]已被替换，原始fileId为:[%s]",orginFdfsInfo.getFsId(), orginFdfsInfo.getFileId()), new Date(),
						CommonUtil.getIp(request), uploadReqBean.getFileName());
				baseErrorInfoService.insert(errlog);
			}else{
				fdfsInfoServiceImpl.insertFdfsInfo(fi);
			}
			
			log.info("文件上传 主文件fileId : " + fileId + " uuid : " + fi.getFsId());
			uploadResBean.setFsId(fi.getFsId());// 设置返回给调用者的id(文件表uuid)
		} catch (Exception e) {
			uploadResBean.setStatus(UploadCtrl.FAILED);
			uploadResBean.setMessage("文件操作失败");
			throw new UploadException(e.getMessage(), HttpStatus.NOT_FOUND);
		}
		return true;
	}

	@Override
	public boolean uploadTypeImg(UploadReqBean uploadReqBean,
			UploadResBean uploadResBean, HttpServletRequest request) throws UploadException {
		MultipartFile file = uploadReqBean.getFile();
		if (file == null || file.getSize() == 0) {
			throw new UploadException("文件内容为空", HttpStatus.UNPROCESSABLE_ENTITY);
		}
		if(StringUtils.isBlank(uploadReqBean.getFileType())) {
			throw new UploadException("文件类型为空", HttpStatus.UNPROCESSABLE_ENTITY);
		}
		String orgFileName = uploadReqBean.getFileName();
		orgFileName = (orgFileName == null) ? "" : orgFileName;
		FdfsInfo fdfsInfo = new FdfsInfo();
		fdfsInfo.setFileName(orgFileName);
		fdfsInfo.setFileSize(file.getSize());// 文件大小
		fdfsInfo.setSlaveName(uploadReqBean.getSlaveName());// 文件缩略图
		fdfsInfo.setFileType(uploadReqBean.getFileType());
		fdfsInfo.setBusinessId(uploadReqBean.getBusinessId());
		fdfsInfo.setSystemId(uploadReqBean.getSystemId());
		Map<String, Object> valiateMap = annexValidatorImpl.validateAnnex(fdfsInfo,ValidatorParmater.FileType.IMG.getKey());// 图片校验
		if(!(boolean) valiateMap.get("success")) {
			uploadResBean.setStatus(UploadCtrl.FAILED);
			uploadResBean.setMessage((String) valiateMap.get("msg"));
			log.warn(uploadResBean.getStatus()+":"+uploadResBean.getMessage());
			return false;
		}
		
		/**增加替换原始文件的验证*/
		FdfsInfo orginFdfsInfo=null;
		if(StringUtils.isNotBlank(uploadReqBean.getOrginFsId())){
			try {
	            orginFdfsInfo=fdfsInfoServiceImpl.selectByPrimaryKey(uploadReqBean.getOrginFsId());
	            if(orginFdfsInfo==null){
	            	throw new Exception("未找到原始文件id:"+uploadReqBean.getOrginFsId());
	            }
            } catch (Exception e) {
    			uploadResBean.setStatus(UploadCtrl.FAILED);
    			uploadResBean.setMessage(e.getMessage());
    			log.warn(uploadResBean.getStatus()+":"+uploadResBean.getMessage());
    			return false;
            }
		}
		
		String tmpOrgFileName = getUUID();
		try {
			String filePath = getRootTmpPath(tmpOrgFileName, "filetmp");// 主文件临时路径
			log.info("上传临时文件 ： " + filePath);
			File masterFile = FileUtil.copyFile(uploadReqBean.getFile().getInputStream(), filePath);// 创建临时文件
			String fileId = FastdfsUtil.getInstance().uploadFile(masterFile, orgFileName, null);// 上传文件到服务器并返回fileId
			log.info("主文件fileId ： " + fileId);
			if(StringUtils.isBlank(fileId)) {//增加fileId 的判断 如果为null 或为空 则返回失败信息
				uploadResBean.setStatus(UploadCtrl.FAILED);
				uploadResBean.setMessage("文件上传失败,未获取到fileId");
				return false;
			}
			//判断是否需要传从文件
			String items[]=new String[0] ;
			if(StringUtils.isNotBlank(uploadReqBean.getSlaveName())){
				items = uploadReqBean.getSlaveName().split(",");// 文件处理拆分
				String slaveFileId = "";
				for (String item : items) {
					String zoom[] = item.split(SystemConfig.PHOTO_SPLIT_ZOOM);// 缩放格式拆分
					String cut[] = item.split(SystemConfig.PHOTO_SPLIT_COORD_POINT);// 裁剪格式拆分
					String slaveFilePath = getRootTmpPath(item + "_" + tmpOrgFileName, "filetmp");// 从文件临时路径
					if (zoom.length == 2) {// 缩放操作
						boolean flag = PhotoUtils.zoomImage(filePath, slaveFilePath, Integer.valueOf(zoom[0]), Integer.valueOf(zoom[1]));
						File slaveFile = new File(slaveFilePath);
						if (flag) {
							slaveFileId = FastdfsUtil.getInstance().uploadSlaveFile(fileId, item, slaveFile, null);// 上传从文件到服务器
							log.info("从文件slaveFileId ： " + slaveFileId);
						} else {// 缩略失败
							uploadResBean.setStatus(UploadCtrl.FAILED);
							uploadResBean.setMessage("文件缩略图创建失败 [" + item + "]");
							deleteFile(slaveFile, masterFile);// 删除临时文件及主文件
							return false;
						}
						deleteFile(slaveFile);// 删除临时创建的从文件
					} else if (cut.length == 2) {// 裁剪操作
						String xy[] = cut[0].split(SystemConfig.PHOTO_SPLIT_COORD_XY);
						String wh[] = cut[1].split(SystemConfig.PHOTO_SPLIT_COORD_XY);
						int x = Integer.valueOf(xy[0]);
						int y = Integer.valueOf(xy[1]);
						int w = Integer.valueOf(wh[0]) - x;
						int h = Integer.valueOf(wh[1]) - y;
						boolean flag = PhotoUtils.cutImage(filePath, slaveFilePath, x, y, w, h);
						File slaveFile = new File(slaveFilePath);
						if (flag) {
							slaveFileId = FastdfsUtil.getInstance().uploadSlaveFile(fileId, item, slaveFile, null);// 上传从文件到服务器
							log.info("从文件slaveFileId ： " + slaveFileId);
						} else {// 裁剪失败
							uploadResBean.setStatus(UploadCtrl.FAILED);
							uploadResBean.setMessage("文件裁剪创建失败 [" + item + "]");
							deleteFile(slaveFile, masterFile);// 删除临时文件及主文件
							return false;
						}
						deleteFile(slaveFile);// 删除临时创建的从文件
					} else {
						uploadResBean.setStatus(UploadCtrl.FAILED);
						uploadResBean.setMessage("缩略裁剪参数错误");
						deleteFile(masterFile);// 删除临时创建及主文件
						return false;
					}
				}
			}
			deleteFile(masterFile);// 删除临时创建的主文件
			FdfsInfo fi = new FdfsInfo();
			fi.setFsId(CommonUtil.getUpperUUID());
			fi.setFileId(fileId);
			fi.setFileName(uploadReqBean.getFileName());
			fi.setFileSize(uploadReqBean.getFile().getSize());
			fi.setBusinessId(uploadReqBean.getBusinessId());
			fi.setFileType(uploadReqBean.getFileType());
			fi.setSlaveName(uploadReqBean.getSlaveName());
			fi.setSystemId(uploadReqBean.getSystemId());
			fi.setSlaveSize(items.length);
			fi.setUploadTime(new Date());
			fi.setUploadIp(CommonUtil.getIp(request));
			
			if(StringUtils.isNotBlank(uploadReqBean.getOrginFsId())){
				//替换原始文件
				fi.setFsId(uploadReqBean.getOrginFsId());
				fdfsInfoServiceImpl.updateFdfsInfoByPrimaryKey(fi);
				ErrorInfo errlog = new ErrorInfo(UUID.randomUUID().toString().replaceAll("-", ""), "upload", 
						String.format("fsid[%s]已被替换，原始fileId为:[%s]",orginFdfsInfo.getFsId(), orginFdfsInfo.getFileId()), new Date(),
						CommonUtil.getIp(request), uploadReqBean.getFileName());
				baseErrorInfoService.insert(errlog);
			}else{
				fdfsInfoServiceImpl.insertFdfsInfo(fi);
			}
			
			log.info("图片上传 主文件fileId : " + fileId + " uuid : " + fi.getFsId());
			uploadResBean.setFsId(fi.getFsId());// 设置返回给调用者的id(文件表uuid)
		} catch (Exception e) {
			uploadResBean.setStatus(UploadCtrl.FAILED);
			uploadResBean.setMessage("图片操作失败");
			throw new UploadException(e.getMessage(), HttpStatus.NOT_FOUND);
		}
		return true;
	}
	
	/**
	 * 
	 * @Title: getFileSuffix
	 * @Description: 获得文件后缀名
	 * @param 文件全名
	 * @return String 后缀名
	 * @throws
	 */
	private String getFileSuffix(String fileName) {
		if (StringUtils.isNotBlank(fileName)) {
			return fileName.substring(fileName.lastIndexOf(".") + 1);
		}
		return ("");
	}

	/**
	 * 
	 * @Title: deleteFile
	 * @Description: 删除文件
	 * @param
	 * @return void
	 * @throws
	 */
	private void deleteFile(File f) {
		if (f.exists())
			f.delete();
	}

	/**
	 * @Title: deleteFile
	 * @Description: 按参数删除文件
	 * @param
	 * @return void
	 * @throws
	 */
	private void deleteFile(File... files) {
		for (File f : files) {
			if (f.exists())
				f.delete();
		}
	}


	/**
	 * @Title: getRootTmpPath
	 * @Description:
	 * @param fileName
	 *            文件名 ...path 文件路径
	 * @return String 文件路径
	 * @throws
	 */
	private String getRootTmpPath(String fileName, String... path) {
		StringBuilder s = new StringBuilder(PathUtil.getRootPath());
		s.append(String.valueOf(File.separatorChar));
		for (String p : path) {
			s.append(p);
			s.append(String.valueOf(File.separatorChar));
		}
		s.append(fileName);
		return s.toString();
	}

	/**
	 * @Title: getUUID
	 * @Description:
	 * @param 获得uuid
	 * @return String
	 * @throws
	 */
	private String getUUID() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

}
